﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ScrewTurn.Wiki;
using ScrewTurn.Wiki.PluginFramework;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Collections;

public partial class NewExperimentTempName : BasePage
{
	private string[] Keys = { "SelectedPulseProgram", "SelectedWaveShapes", "SelectedCPDs", "SelectedScripts" };

	private Dictionary<string, string> Components = null;

	private void Page_Init(object sender, System.EventArgs e)
	{
		if (!Page.IsPostBack)
		{
			foreach (string k in Keys)
			{
				Dictionary<string, string> Dict = (Dictionary<string, string>)Session[k];
				if (Dict != null) Dict.Clear();
			}
		}
		foreach (string k in Keys)
		{
			if (Session[k] != null) Components = Session[k] as Dictionary<string, string>;
			else
			{
				Components = new Dictionary<string, string>();
				Session[k] = Components;
			}

			foreach (KeyValuePair<string, string> kvpComp in Components) AddComponentControl(k, kvpComp);
		}
	}

	private void AddComponentControl(string Key, KeyValuePair<string, string> NameId)
	{
		//Where to add control is desided based on Key
		Label Elem;	//Label Control Where the components entries will be added as childs
		switch (Key)
		{
			case "SelectedPulseProgram":
				Elem = lblSelectedPulseProgram;
				break;
			case "SelectedWaveShapes":
				Elem = lblSelectedWaveShapes;
				break;
			case "SelectedCPDs":
				Elem = lblSelectedCPDs;
				break;
			case "SelectedScripts":
				Elem = lblSelectedScripts;
				break;
			default:
				throw new NotImplementedException("Add Component Control: default Key is bad");
		}

		//New Panel Wrapper
		Panel p = new Panel();
		p.ID = "pan" + NameId.Value + "_" + NameId.Key;
		Elem.Controls.Add(p);
		//New Label carring Name and ID  of component
		Label t = new Label();
		t.Width = 250;
		t.Text = string.Format("<b>{0} with ID {1}</b>", NameId.Value, NameId.Key);
		p.Controls.Add(t);
		Debug.WriteLine(string.Format("x.Key={0}; cKey={1}", NameId.Key, Key));

		//New Image Button 
		ImageButton b = new ImageButton();
		b.AlternateText = "Remove";
		b.ID = "ib" + NameId.Value + "_" + NameId.Key;
		b.CssClass = "RemoveButton";
		b.CausesValidation = false;
		b.CommandArgument = NameId.Key;
		b.CommandName = Key;
		b.Command += new CommandEventHandler(RemoveComponent);
		p.Controls.Add(b);

		AsyncPostBackTrigger a = new AsyncPostBackTrigger();
		a.ControlID = b.UniqueID;
		a.EventName = "Command";
		uppanComponents.Triggers.Add(a);

		//Label dlbl = new Label();
		//dlbl.Text = string.Format("b.ID={2}, b.ComArg={0}, b.ComName={1}", b.CommandArgument, b.CommandName, b.ID);
		//p.Controls.Add(dlbl);

		LiteralControl l = new LiteralControl("<br />");
		p.Controls.Add(l);
		//	uppanComponents.Update();

	}

	protected void Page_Load(object sender, EventArgs e)
	{
		#region Verify Authentication
		// Re-verify authentication
		PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);
		if (pageInfo == null)
		{
			// Page creation
			if (SessionFacade.LoginKey == null && !Settings.PublicAccess)
			{
				Response.Redirect("Login.aspx?Redirect=DesignExperiment.aspx");
			}
			if (!Settings.UsersCanCreateNewPages && !SessionFacade.Admin)
			{
				Response.Redirect("AccessDenied.aspx");
			}
		}
		else
		{
			// Page modification
			if (pageInfo.Provider.ReadOnly) Response.Redirect(pageInfo.Name + Settings.PageExtension);

			if (pageInfo.Status == PageStatus.Locked)
			{
				if (SessionFacade.LoginKey == null || (SessionFacade.LoginKey != null && (SessionFacade.LoginKey == null || !SessionFacade.Admin)))
				{
					Response.Redirect("AccessDenied.aspx");
				}
			}

			// Login/Authorization check
			if (SessionFacade.LoginKey == null && !Settings.PublicAccess && pageInfo.Status != PageStatus.Public)
			{
				Response.Redirect("Login.aspx?Redirect=" + Tools.UrlEncode(Request.Url.ToString().Substring(Request.Url.ToString().ToLowerInvariant().IndexOf("Experiments.aspx"))));
			}
			if ((Settings.PublicAccess || pageInfo.Status == PageStatus.Public) && SessionFacade.LoginKey == null)
			{
				//lblIpLogged.Visible = true;
			}
		}
		#endregion

		tbType.MaxLength = Constants.TypeLength;
		tbContent.MaxLength = Constants.ContentLength;
		tbName.MaxLength = Constants.NameLength;
		tbMemo.MaxLength = Constants.MemoLength;
		
	}

	#region Components
	protected void SelectComponent(object sender, GridViewCommandEventArgs e)
	{
		Label Elem;
		GridView currentGridView;
		string CompID;
		string CompName;
		string currentKey;
		int currentRowIndex = -5;

		try
		{
			currentRowIndex = Int32.Parse(e.CommandArgument.ToString());
		}
		catch
		{
			if (currentRowIndex < 0)
				return;
		}
		switch (e.CommandName)
		{
			case "SelectPulseProgram":
				//	WhereTo = ibAddPP;
				Elem = lblSelectedPulseProgram;
				currentGridView = PulseProgramsTable;
				currentKey = "SelectedPulseProgram";
				ibAddPP.Visible = false;
				break;
			case "SelectWaveShape":
				//	WhereTo = lbAddWS;
				Elem = lblSelectedWaveShapes;
				currentGridView = WaveShapesTable;
				currentKey = "SelectedWaveShapes";
				break;
			case "SelectCPD":
				currentGridView = CPDsTable;
				//	WhereTo = lbAddCPD;
				currentKey = "SelectedCPDs";
				Elem = lblSelectedCPDs;
				break;
			case "SelectScript":
				//	WhereTo = lbAddScr;
				currentGridView = ScriptsTable;
				currentKey = "SelectedScripts";
				Elem = lblSelectedScripts;
				break;
			default:
				return;
		}
		CompID = currentGridView.DataKeys[currentRowIndex].Value.ToString();
		CompName = currentGridView.DataKeys[currentRowIndex].Values[1].ToString();

		Elem.Visible = true;

		mvSelectComponent.Visible = false;

		Dictionary<string, string> Dict = (Dictionary<string, string>)Session[currentKey];
		try
		{
			Dict.Add(CompID, CompName);
		}
		catch
		{
			return;
		}

		Debug.WriteLine("ShowComponents from SelectComponent");
		AddComponentControl(currentKey, new KeyValuePair<string, string>(CompID, CompName));
		//uppanComponents.Update();
	}

	private void RemoveComponent(object sender, CommandEventArgs e)
	{

		Debug.WriteLine(string.Format("Sender {0}, UID={3}; ComandName = {1}, commandarg={2}", ((ImageButton)sender).ClientID, e.CommandName, e.CommandArgument, ((ImageButton)sender).UniqueID));
		Dictionary<string, string> Dict = (Dictionary<string, string>)Session[e.CommandName];
		string cKey = e.CommandArgument.ToString();
		string cValue = Dict[cKey];
		string ibID = ((ImageButton)sender).ID;

		try
		{
			Dict.Remove(e.CommandArgument.ToString());
		}
		catch { }

		Label Elem;
		switch (e.CommandName)
		{
			case "SelectedPulseProgram":
				Elem = lblSelectedPulseProgram;
				ibAddPP.Visible = true;
				break;
			case "SelectedWaveShapes":
				Elem = lblSelectedWaveShapes;
				break;
			case "SelectedCPDs":
				Elem = lblSelectedCPDs;
				break;
			case "SelectedScripts":
				Elem = lblSelectedScripts;
				break;
			default:
				return;
		}
		Debug.WriteLine("ShowComponents from Remove Component");


		foreach (Control x in Elem.Controls)
		{
			Panel p = x as Panel;
			if (p == null) continue;
			if (p.ID == "pan" + cValue + "_" + cKey)
			{

				Elem.Controls.Remove(p);
			}
		}

	}

	protected void RefreshTable(object sender, CommandEventArgs e)
	{
		switch (e.CommandName)
		{
			case "RefreshPulsePrograms":
				PulseProgramsTable.DataBind();
				break;
			case "RefreshWaveShapes":
				WaveShapesTable.DataBind();
				break;
			case "RefreshCPDs":
				CPDsTable.DataBind();
				break;
			case "RefreshScripts":
				ScriptsTable.DataBind();
				break;
			default:
				throw new NotImplementedException("Refresh Table Default");
		}
	}
	#endregion

	protected void butSubmit_Command(object sender, CommandEventArgs e)
	{
		if (!Page.IsValid) return;

		string QueryText = "";
		SqlDataReader MainReader = null;

		SqlConnection myConnection = new SqlConnection(Constants.NMRExperimentsConStr);
		myConnection.Open();

		string currentPulseProgram = ((Dictionary<string,string>)Session[Keys[0]]).Keys.First();

		//Add Experiments
		string ExpID = addExperimentToDB(currentPulseProgram, myConnection);

		string currentAuthorID = null; // Used to keep newly added authors ID

		foreach (DictionaryEntry x in AuthorsList.SelectedAuthors)
		{
			currentAuthorID = (string)x.Key;

			if (x.Value is Authors.Author)   // Means name is new, needs to be added to DB
			{
				Authors.Author cAuthor = (Authors.Author)x.Value;
				using (SqlCommand QueryInsertNewAuthor = myConnection.CreateCommand())
				{
					QueryInsertNewAuthor.CommandText =
@"INSERT INTO authors  (authfn, authmn, authln)
 VALUES (@fn, @mn, @ln)
SELECT @@IDENTITY";

					QueryInsertNewAuthor.Parameters.Add(new SqlParameter("@fn", cAuthor.FirstName));
					QueryInsertNewAuthor.Parameters.Add(new SqlParameter("@mn", cAuthor.MiddleName));
					QueryInsertNewAuthor.Parameters.Add(new SqlParameter("@ln", cAuthor.LastName));

					currentAuthorID = QueryInsertNewAuthor.ExecuteScalar().ToString();
				}
			}

			using (SqlCommand QueryInsertAuthorsComponentRelation = myConnection.CreateCommand())
			{
				QueryInsertAuthorsComponentRelation.CommandText =
@"INSERT INTO relation_experiments_to_##secondforeignkeyreftable## 
VALUES (@FieldID, @AuthorID, @AuthorNumber)"
.Replace("##secondforeignkeyreftable##", "authors");

				QueryInsertAuthorsComponentRelation.Parameters.Add(new SqlParameter("@FieldID", ExpID));
				QueryInsertAuthorsComponentRelation.Parameters.Add(new SqlParameter("@AuthorID", currentAuthorID));
				QueryInsertAuthorsComponentRelation.Parameters.Add(new SqlParameter("@AuthorNumber", Convert.ToString(AuthorsList.SelectedAuthors.GetIndexOf(x.Key))));

				QueryInsertAuthorsComponentRelation.ExecuteScalar();
			}
		}
		
		Dictionary<string, string> CompCollectionIDs;
		SqlCommand MainInsert=myConnection.CreateCommand();
		string TargetTable;
		string BasicQuery = @"INSERT INTO relation_##firstforeignkeyreftable##_to_##secondforeignkeyreftable## VALUES (##foreignkey1##, ##foreignkey2##);";
		//Add Relations Experiment to WaveShapes
		CompCollectionIDs = (Dictionary<string,string>)Session[Keys[1]];
		TargetTable = "waveshapes";
		foreach(KeyValuePair<string,string> x in CompCollectionIDs)
		{
			QueryText = BasicQuery;
			QueryText = QueryText.Replace("##firstforeignkeyreftable##", TargetTable);
			QueryText = QueryText.Replace("##secondforeignkeyreftable##", "experiments");
			QueryText = QueryText.Replace("##foreignkey1##", x.Key);
			MainInsert.CommandText = QueryText.Replace("##foreignkey2##", ExpID);
			MainReader = MainInsert.ExecuteReader();
			MainReader.Close();
		}


		CompCollectionIDs = (Dictionary<string, string>)Session[Keys[2]];
		TargetTable = "cpds";
		foreach (KeyValuePair<string, string> x in CompCollectionIDs)
		{
			QueryText = BasicQuery;
			QueryText = QueryText.Replace("##firstforeignkeyreftable##", TargetTable);
			QueryText = QueryText.Replace("##secondforeignkeyreftable##", "experiments");
			QueryText = QueryText.Replace("##foreignkey1##", x.Key);
			MainInsert.CommandText = QueryText.Replace("##foreignkey2##", ExpID);
			MainReader = MainInsert.ExecuteReader();
			MainReader.Close();
		}

		CompCollectionIDs = (Dictionary<string, string>)Session[Keys[3]];
		TargetTable = "scripts";
		foreach (KeyValuePair<string, string> x in CompCollectionIDs)
		{
			QueryText = BasicQuery;
			QueryText = QueryText.Replace("##firstforeignkeyreftable##", TargetTable);
			QueryText = QueryText.Replace("##secondforeignkeyreftable##", "experiments");
			QueryText = QueryText.Replace("##foreignkey1##", x.Key);
			MainInsert.CommandText = QueryText.Replace("##foreignkey2##", ExpID);
			MainReader = MainInsert.ExecuteReader();
			MainReader.Close();
		}
		myConnection.Close();

		UniBasel.Biozentrum.NMR.NMRGenUtils.createWikiPage("Experiment", ExpID, tbName.Text);

#if DEBUG
		//string Damn = "";
		//Dictionary<string, string> Dict;
		//foreach (string k in Keys)
		//{
		//    Dict = (Dictionary<string, string>)Session[k];
		//    Damn += string.Format("Dictionary {0} has {1} members.\n", k, Dict.Count);
		//    foreach (KeyValuePair<string, string> x in Dict)
		//    {
		//        Damn += string.Format("Key={0}; Value={1}\n", x.Key, x.Value);
		//    }
		//    Damn += "\n";

		//}
		//Damn += string.Format("Labels have {0}, {1}, {2}, {3} child controls.\n", lblSelectedPulseProgram.Controls.Count, lblSelectedWaveShapes.Controls.Count, lblSelectedCPDs.Controls.Count, lblSelectedScripts.Controls.Count);
		//tbContent.Text = Damn;
#endif
		
		Response.Redirect("Experiments.aspx");
	}

	private string addExperimentToDB(string PulseProgramID, SqlConnection myConnection)
	{
		string QueryText;
		SqlDataReader MainReader;

		SqlCommand MainInsert = myConnection.CreateCommand();

		//Check if Experiment Type is already in DB
		//If not, add new entry
		#region
		string currentType = tbType.Text;

		QueryText = @"SELECT name FROM types t WHERE name = '##checktype##'";
		QueryText = QueryText.Replace("##checktype##", currentType);

		MainInsert.CommandText = QueryText;
		MainReader = MainInsert.ExecuteReader();
		if (!MainReader.HasRows) //if Select command did not return rows insert new type ##inserttypename##
		{
			MainReader.Close();
			QueryText = @"INSERT INTO types (name) VALUES ('##inserttypename##')";
			QueryText =QueryText.Replace("##inserttypename##", currentType);
			MainInsert.CommandText = QueryText;
			MainReader = MainInsert.ExecuteReader();
		}
		MainReader.Close();
		#endregion	

		QueryText = @"
INSERT
  INTO ##table## (name, dim, memo, content, version, versionupdateinfo, firstversionid, previousversionid, pulseprogram, type)
VALUES
  ('##insertname##', '##insertdimentionality##', '##insertmemo##', '##insertcontent##', ##insertvernumber##, '##insertupdateinfo##', ##insertfirstverid##, ##insertprevversionid##, ##insertpulseprogramid##, '##inserttype##');";
		QueryText = QueryText.Replace("##table##", "experiments");
		QueryText = QueryText.Replace("##insertname##", tbName.Text);
		QueryText = QueryText.Replace("##insertdimentionality##", genDimentionality.SelectedValue.ToString());
		QueryText = QueryText.Replace("##insertmemo##", tbMemo.Text);
		QueryText = QueryText.Replace("##insertcontent##", tbContent.Text.Replace(@"'", @"''"));
		QueryText = QueryText.Replace("##insertvernumber##", "1");
		QueryText = QueryText.Replace("##insertupdateinfo##", "Initial Release");
		QueryText = QueryText.Replace("##insertfirstverid##", "1");
		QueryText = QueryText.Replace("##insertprevversionid##", "1");
		QueryText = QueryText.Replace("##insertpulseprogramid##", PulseProgramID);
		QueryText = QueryText.Replace("##inserttype##", currentType);

		MainInsert.CommandText = QueryText;

		MainReader = MainInsert.ExecuteReader();
		MainReader.Close();

		SqlCommand getLastInsertedID = myConnection.CreateCommand();
		getLastInsertedID.CommandText = @"SELECT @@IDENTITY";

		long FieldID = Convert.ToInt32(getLastInsertedID.ExecuteScalar());

		return FieldID.ToString();
	}

	protected void butClear_Click(object sender, EventArgs e)
	{
		tbName.Text = string.Empty;
		genDimentionality.SelectedIndex = 0;
		tbMemo.Text = string.Empty;
		tbType.Text = string.Empty;
		AuthorsList.Clear();
		tbContent.Text = string.Empty;

		foreach (string x in Keys)
		{
			((Dictionary<string, string>)Session[x]).Clear();
		}

		lblSelectedPulseProgram.Text = "";
		lblSelectedPulseProgram.Visible = false;
		ibAddPP.Visible = true;

		lblSelectedWaveShapes.Text = "";
		lblSelectedWaveShapes.Visible = false;

		lblSelectedCPDs.Text = "";
		lblSelectedCPDs.Visible = false;

		lblSelectedScripts.Text = "";
		lblSelectedScripts.Visible = false;
	}

	#region Custom Validators
	protected void ValidatePulseProgram(object source, ServerValidateEventArgs args)
	{
		Dictionary<string, string> Dict = (Dictionary<string, string>)Session["SelectedPulseProgram"];
		args.IsValid = true;
		if (Dict.Count != 1) args.IsValid = false;
	}

	protected void ValidateAuthorsNumber(object source, ServerValidateEventArgs args)
	{
		args.IsValid = (int.Parse(args.Value) < 1) ? false : true;
	}

	protected void ValidateForScripts(object source, ServerValidateEventArgs args)
	{
		args.IsValid = !Regex.IsMatch(args.Value.ToString(), @"\<script.*?\>");
	}
	#endregion

	protected void lbAdd_Command(object sender, CommandEventArgs e)
	{
		mvSelectComponent.Visible = true;
		switch (e.CommandArgument.ToString())
		{
			case "pp":
				mvSelectComponent.ActiveViewIndex = 0;
				break;
			case "ws":
				mvSelectComponent.ActiveViewIndex = 1;
				break;
			case "cpd":
				mvSelectComponent.ActiveViewIndex = 2;
				break;
			case "scr":
				mvSelectComponent.ActiveViewIndex = 3;
				break;
			default:
				mvSelectComponent.ActiveViewIndex = 4;
				break;
		}
	}
}
